/**
 * 
 */
package biz.innovasoft.test.units;

import static biz.innovasoft.ndb.query.QueryCriteriaUtil.eq;
import static biz.innovasoft.ndb.query.QueryCriteriaUtil.range;

import java.util.ArrayList;
import java.util.List;

import junit.framework.TestCase;
import biz.innovasoft.ndb.PrevalentRepositoryManager;
import biz.innovasoft.ndb.Repository;
import biz.innovasoft.ndb.query.QueryCriteria;
import biz.innovasoft.ndb.query.Result;
import biz.innovasoft.ndb.query.Tuple;
import biz.innovasoft.test.model.MedicineStudent;
import biz.innovasoft.test.model.Person;
import biz.innovasoft.test.model.Student;


/**
 * 
 * @author Diego Miranda
 *
 */
public class NoDBTestCase extends TestCase {

	/**
	 * Test store objects.
	 */
	public void testWrite () {
		
		PrevalentRepositoryManager manager = PrevalentRepositoryManager.getInstance();
		Repository repository = manager.openRepository("TestRepo", true);
		
		Long oid = repository.store(TestUtils.newPerson(), false);
		int repoSize = repository.size();
		int personSize = repository.size(Person.class);
		
		// Easy check, all must be 1
		assertEquals((long)1, (long)oid);
		assertEquals(1, repoSize);
		assertEquals(1, personSize);
		
		List<Student>students = new ArrayList<Student>();
		for (int t=0; t < 100; t++) {
			students.add(TestUtils.newStudent());
		}
		
		repository.store(students, false);
		
		// Now i should have 101 objects inside the repository.
		repoSize = repository.size();
		personSize = repository.size(Person.class);
		int studentSize = repository.size(Student.class);
		
		assertEquals (101, repoSize);
		assertEquals (1, personSize);
		assertEquals (100, studentSize);
		
		manager.closeRepository("TestRepo");
	}
	
	/**
	 * Test the inheritance with QueryCriteria.
	 */
	public void testInheritance () {
		PrevalentRepositoryManager manager = PrevalentRepositoryManager.getInstance();
		Repository repository = manager.openRepository("TestRepo", true);
		
		List<Student>students = new ArrayList<Student>();
		for (int t=0; t < 100; t++) {
			students.add(TestUtils.newStudent());
		}
		repository.store(students, true);
		repository.store(TestUtils.newPerson());
		
		QueryCriteria personsQuery = repository.createCriteria(Person.class).maxResults(300);
		Result personsResult = personsQuery.find();
		QueryCriteria studentsQuery = repository.createCriteria(Student.class).maxResults(300);
		Result studentsResult = studentsQuery.find();
		
		assertEquals (101, personsResult.size());
		assertEquals (100, studentsResult.size());
		
		manager.closeRepository("TestRepo");
	}
	
	/**
	 * Test the QueryCriteria with indexes.
	 */
	public void testQueryByIndex () {
		PrevalentRepositoryManager manager = PrevalentRepositoryManager.getInstance();
		Repository repository = manager.openRepository("TestRepo", true);
		
		repository.createIndex(Person.class, "name");
		repository.createIndex(Person.class, "lastName");
		
		List<Student>students = new ArrayList<Student>();
		for (int t=0; t < 100; t++) {
			students.add(TestUtils.newStudent());
		}
		repository.store(students, true);
		repository.store(TestUtils.newPerson());
		
		QueryCriteria personsQuery = repository.createCriteria(Person.class).
											where (eq("name", "Darky")).maxResults(300);
		Result result = personsQuery.find();
		assertEquals (false, result.getUseTemporalIndex());
		
		QueryCriteria studentsQuery = repository.createCriteria(Student.class).
										where (eq("name", "Darky")).maxResults(300);
		result = studentsQuery.find();
		assertEquals (false, result.getUseTemporalIndex());
		
		manager.closeRepository("TestRepo");
	}
	
	/**
	 * Test the QueryCriteria without indexes.
	 */
	public void testQueryWithoutIndex () {
		PrevalentRepositoryManager manager = PrevalentRepositoryManager.getInstance();
		Repository repository = manager.openRepository("TestRepo", true);
		
		List<Student>students = new ArrayList<Student>();
		for (int t=0; t < 100; t++) {
			students.add(TestUtils.newStudent());
		}
		repository.store(students, true);
		repository.store(TestUtils.newPerson());
		
		QueryCriteria personsQuery = repository.createCriteria(Person.class).
											where (eq("name", "Darky")).maxResults(300);
		Result result = personsQuery.find();
		assertEquals (true, result.getUseTemporalIndex());
		
		QueryCriteria studentsQuery = repository.createCriteria(Person.class).
										where (eq("name", "Darky")).maxResults(300);
		result = studentsQuery.find();
		assertEquals (true, result.getUseTemporalIndex());
		
		manager.closeRepository("TestRepo");
	}
	
	/**
	 * Test delete objects and then find them and check the size and the inheritance.
	 */
	public void testDeleteAndInheritance () {
		PrevalentRepositoryManager manager = PrevalentRepositoryManager.getInstance();
		Repository repository = manager.openRepository("TestRepo", true);
		
		List<Student>students = new ArrayList<Student>();
		for (int t=0; t < 100; t++) {
			students.add(TestUtils.newStudent());
			students.add(TestUtils.newMedicineStudent());
		}
		repository.store(students, true);
		repository.store(TestUtils.newPerson());
		
		QueryCriteria personsQuery = repository.createCriteria(Person.class).maxResults(300);
		Result personsResult = personsQuery.find();
		QueryCriteria studentsQuery = repository.createCriteria(Student.class).maxResults(300);
		Result studentsResult = studentsQuery.find();
		
		assertEquals (201, personsResult.size());
		assertEquals (200, studentsResult.size());
		
		// Now delete Students
		repository.delete(Student.class);
		
		personsQuery = repository.createCriteria(Person.class).maxResults(300);
		personsResult = personsQuery.find();
		studentsQuery = repository.createCriteria(Student.class).maxResults(300);
		studentsResult = studentsQuery.find();
		
		assertEquals (101, personsResult.size());
		assertEquals (100, studentsResult.size());
		
		repository.delete(Person.class);
		
		personsQuery = repository.createCriteria(Person.class).maxResults(300);
		personsResult = personsQuery.find();
		studentsQuery = repository.createCriteria(MedicineStudent.class).maxResults(300);
		studentsResult = studentsQuery.find();
		
		assertEquals (100, personsResult.size());
		assertEquals (100, studentsResult.size());
		assertEquals (0, repository.size(Person.class));
		assertEquals (0, repository.size(Student.class));
		assertEquals (100, repository.size());
		
		manager.closeRepository("TestRepo");
	}
	
	/**
	 * Test update.
	 */
	public void testUpdate () {
		PrevalentRepositoryManager manager = PrevalentRepositoryManager.getInstance();
		Repository repository = manager.openRepository("TestRepo", true);
		
		List<Student>students = new ArrayList<Student>();
		for (int t=0; t < 100; t++) {
			students.add(TestUtils.newStudent());
		}
		repository.store(students, true);
		
		assertEquals (100, repository.size());
		
		QueryCriteria query = repository.createCriteria(Person.class).maxResults(300);
		Result result = query.find();
		for (Tuple tuple : result) {
			Person p = (Person)tuple.value;
			p.setName ( "Garrafa" );
			repository.update(tuple.oid, p);
		}
		
		assertEquals (100, repository.size());
		assertEquals (100, result.getTotalHits());
		
		result = query.find();
		for (Tuple tuple : result) {
			Person p = (Person)tuple.value;
			assertEquals ("Garrafa", p.getName());
		}
		
		manager.closeRepository("TestRepo");
	}
	
	/**
	 * Test the order by.
	 */
	public void testQueryOrderBy () {
		PrevalentRepositoryManager manager = PrevalentRepositoryManager.getInstance();
		Repository repository = manager.openRepository("TestRepo", true);
		
		repository.createIndex(Student.class, "age");
		repository.createIndex(Student.class, "name");
		
		List<Student>students = new ArrayList<Student>();
		for (int t=0; t < 100; t++) {
			students.add(TestUtils.newStudent());
		}
		repository.store(students, true);
		
		QueryCriteria query = repository.createCriteria(Student.class, true).maxResults(100);
		query.where(eq("name", "Darky")).orderBy("age");
		Result result = query.find();
		int count = 0;
		int max = result.getTotalHits();
		
		Tuple prev = result.get(count);
		do {
			Tuple next = result.get(count++);
			Student ps = (Student)prev.value;
			Student ns = (Student)next.value;
			assertEquals (true, (ps.getAge() <= ns.getAge()));
			prev = next;
		} while (count < max);
	}
	
	/**
	 * Test the range.
	 */
	public void testQueryRangeAndOrderBy () {
		PrevalentRepositoryManager manager = PrevalentRepositoryManager.getInstance();
		Repository repository = manager.openRepository("TestRepo", true);
		
		repository.createIndex(Student.class, "age");
		repository.createIndex(Student.class, "name");
		
		List<Student>students = new ArrayList<Student>();
		for (int t=0; t < 100; t++) {
			Student s = TestUtils.newStudent();
			s.setAge(t+1);
			students.add(s);
		}
		repository.store(students, true);
		
		QueryCriteria query = repository.createCriteria(Student.class, true).maxResults(100);
		query.where(range("age", 10, 20)).orderBy("age");
		Result result = query.find();
		int count = 0;
		int max = result.getTotalHits();
		
		Tuple prev = result.get(count);
		do {
			Tuple next = result.get(count++);
			Student ps = (Student)prev.value;
			Student ns = (Student)next.value;
			assertEquals (true, (ns.getAge() >= 10) && (ns.getAge() <= 20));
			assertEquals (true, (ps.getAge() <= ns.getAge()));
			prev = next;
		} while (count < max);
	}
}
